package com.mingle.widget;

import com.mingle.widget.listener.MyAnimatorStateChangedListener;
import com.mingle.widget.utils.AttrUtil;
import com.mingle.widget.utils.ViewHelper;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.AttrSet;
import ohos.agp.components.LayoutScatter;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

/**
 * Created by zzz40500 on 15/4/6.
 */
public class LoadingView extends DirectionalLayout implements Component.BindStateChangedListener {

    private final String LOADINGVIEW_LOADINGTEXT = "loadingText";
    private final String LOADINGVIEW_LOADINGTEXTCOLOR = "loadingTextColor";
    private final String LOADINGVIEW_LOADINGTEXTSIZE = "loadingTextSize";
    private final String LOADINGVIEW_DELAY = "delay";

    private static final int ANIMATION_DURATION = 500;
    private static float mDistance = 200;
    private static final int MSG = 0;
    private ShapeLoadingView mShapeLoadingView;
    private Image mIndicationIm;
    private Text mLoadTextView;
    private AnimatorGroup mUpAnimatorSet;
    private AnimatorGroup mDownAnimatorSet;
    private boolean mStopped = false;
    private int mDelay;

    public LoadingView(Context context) {
        this(context, null);
    }

    public LoadingView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public LoadingView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context, attrSet);
    }

    private void init(Context context, AttrSet attrSet) {
        setOrientation(VERTICAL);
        mDistance = vp2px(context, 54f);
        LayoutScatter.getInstance(context).parse(ResourceTable.Layout_load_view, this, true);
        mShapeLoadingView = (ShapeLoadingView) findComponentById(ResourceTable.Id_shapeLoadingView);
        mIndicationIm = (Image) findComponentById(ResourceTable.Id_indication);
        mLoadTextView = (Text) findComponentById(ResourceTable.Id_promptTV);
        ViewHelper.setScaleX(mIndicationIm, 0.2f);

        AttrUtil attrUtil = new AttrUtil(attrSet);
        String loadText = attrUtil.getStringValue(LOADINGVIEW_LOADINGTEXT, "");
        int textColor = attrUtil.getColorValue(LOADINGVIEW_LOADINGTEXTCOLOR, 0xff757575);
        int textSize = attrUtil.getDimensionValue(LOADINGVIEW_LOADINGTEXTSIZE, -1);
        mDelay = attrUtil.getIntegerValue(LOADINGVIEW_DELAY, 80);

        mLoadTextView.setTextColor(new Color(textColor));
        if (textSize >= 0) {
            mLoadTextView.setTextSize(textSize);
        }
        setLoadingText(loadText);
        setBindStateChangedListener(this);
        setLayoutRefreshedListener(new LayoutRefreshedListener() {
            @Override
            public void onRefreshed(Component component) {
                onFinishInflate();
            }
        });
    }

    private void onFinishInflate() {
        if (getVisibility() == VISIBLE) {
            startLoading(mDelay);
        }
    }

    private EventHandler mFreeFallHandler = new EventHandler(EventRunner.getMainEventRunner()) {
        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event.eventId == MSG) {
                removeEvent(MSG);
                ViewHelper.setRotation(mShapeLoadingView, 180f);
                ViewHelper.setTranslationY(mShapeLoadingView, 0f);
                ViewHelper.setScaleX(mIndicationIm, 0.2f);
                mStopped = false;
                freeFall();
            }
        }
    };

    private void startLoading(long delay) {
        if (mDownAnimatorSet != null && mDownAnimatorSet.isRunning()) {
            return;
        }
        mFreeFallHandler.removeEvent(MSG);
        mFreeFallHandler.sendEvent(MSG, delay > 0 ? delay : 0);
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        stopLoading();
    }

    private void stopLoading() {
        mStopped = true;
        if (mUpAnimatorSet != null) {
            if (mUpAnimatorSet.isRunning()) {
                mUpAnimatorSet.cancel();
            }
            mUpAnimatorSet.release();
            mUpAnimatorSet.clear();
            mUpAnimatorSet = null;
        }
        if (mDownAnimatorSet != null) {
            if (mDownAnimatorSet.isRunning()) {
                mDownAnimatorSet.cancel();
            }
            mDownAnimatorSet.release();
            mDownAnimatorSet.clear();
            mDownAnimatorSet = null;
        }
        mFreeFallHandler.removeEvent(MSG);
    }

    @Override
    public void setVisibility(int visibility) {
        this.setVisibility(visibility, mDelay);
    }

    private void setVisibility(int visibility, int delay) {
        super.setVisibility(visibility);
        if (visibility == VISIBLE) {
            startLoading(delay);
        } else {
            stopLoading();
        }
    }

    /**
     * 设置延迟显示的时间
     * @param delay 延迟显示的时间
     */
    public void setDelay(int delay) {
        mDelay = delay;
    }

    /**
     * 获取延迟显示的时间
     * @return 延迟显示的时间
     */
    public int getDelay() {
        return mDelay;
    }

    /**
     * 设置loading文本
     * @param loadingText loading文本
     */
    public void setLoadingText(String loadingText) {
        if (loadingText != null && isEmpty(loadingText)) {
            mLoadTextView.setVisibility(HIDE);
        } else {
            mLoadTextView.setVisibility(VISIBLE);
        }
        mLoadTextView.setText(loadingText);
    }

    /**
     * 获取loading文本
     * @return loading文本
     */
    public String getLoadingText() {
        return mLoadTextView.getText();
    }

    /**
     * 获取loading中的文本控件
     * @return loading中的文本控件
     */
    public Text getLoadingTextView() {
        return mLoadTextView;
    }

    /**
     * 上抛
     */
    private void upThrow() {
        mShapeLoadingView.setRotation(0);
        if (mUpAnimatorSet == null) {
            AnimatorProperty objectAnimator = mShapeLoadingView.createAnimatorProperty().moveFromY(mDistance).moveToY(0).rotate(180);
            AnimatorProperty scaleIndication = mIndicationIm.createAnimatorProperty().scaleXFrom(1f).scaleX(0.2f);
            mUpAnimatorSet = new AnimatorGroup();
            mUpAnimatorSet.runParallel(objectAnimator, scaleIndication);
            mUpAnimatorSet.setDuration(ANIMATION_DURATION);
            mUpAnimatorSet.setCurveType(Animator.CurveType.DECELERATE);
            mUpAnimatorSet.setStateChangedListener(new MyAnimatorStateChangedListener() {
                @Override
                public void onEnd(Animator animator) {
                    if (!mStopped) {
                        freeFall();
                    }
                }
            });
        }
        mUpAnimatorSet.start();
    }

    /**
     * 下落
     */
    private void freeFall() {
        if (mDownAnimatorSet == null) {
            AnimatorProperty objectAnimator = mShapeLoadingView.createAnimatorProperty().moveFromY(0).moveToY(mDistance);
            AnimatorProperty scaleIndication = mIndicationIm.createAnimatorProperty().scaleXFrom(0.2f).scaleX(1.0f);
            mDownAnimatorSet = new AnimatorGroup();
            mDownAnimatorSet.runParallel(objectAnimator, scaleIndication);
            mDownAnimatorSet.setDuration(ANIMATION_DURATION);
            mDownAnimatorSet.setCurveType(Animator.CurveType.ACCELERATE);
            mDownAnimatorSet.setStateChangedListener(new MyAnimatorStateChangedListener() {
                @Override
                public void onEnd(Animator animator) {
                    if (!mStopped) {
                        mShapeLoadingView.changeShape();
                        upThrow();
                    }
                }
            });
        }
        mDownAnimatorSet.start();
    }

    @Override
    public void onComponentBoundToWindow(Component component) {

    }

    private int vp2px(Context context, float vpValue) {
        return (int) (context.getResourceManager().getDeviceCapability().screenDensity / 160 * vpValue);
    }

    private boolean isEmpty(CharSequence str) {
        if (str != null) {
            return str.length() == 0;
        }
        return true;
    }

}
